/*
 * clogo.c
 *
 *  Created on: Dec 16, 2010
 *      Author: cpy.prefers.you@gmail.com
 */

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include "clogo.h"
#include "buildin_commands.h"
#include "symbol_table.h"
#include "error_handling.h"
#include "lexer.h"
#include "parser.h"

int RecursiveInterprete;

static const char WelcomeMessage[] =
{
    "\n"
    "Welcome to CLogo version %s by %s\n"
    "Please note this is a development version of CLogo, which can be very unstable. Try it with care.\n"
    "See README or type \"help\" for detailed information.\n"
};

static const char ExitMessage[] =
{
    "\nThank you for using CLogo.\nHave a nice day.\n"
};

static char *_InputPointer;

FILE *InputStream;
FILE *OutputStream;
int PrintLN;
char *PrimaryPrompt = "? ";
char *SecondaryPrompt = "~ ";

static void CLogoInit();

static void CLogoInit()
{
    InputStream = stdin;
    OutputStream = stdout;
#ifdef OS_WINDOWS
    char TempPath[TOKEN_LEN];
    char TempFileName[TOKEN_LEN];
    GetTempPath(TOKEN_LEN, TempPath);
    GetTempFileName(TempPath, "", 0, TempFileName);
    TempFile = fopen(TempFileName, "w+b");
#else
    TempFile = tmpfile();
    while (!TempFile)
        TempFile = tmpfile();
#endif
    fprintf(OutputStream, WelcomeMessage, VERSION, AUTHOR);
    return;
}

void CLogoFinalize()
{
    fprintf(OutputStream, ExitMessage);
    fclose(TempFile);
    #ifdef OS_WINDOWS
        DeleteFile(TempFileName);
    #endif
    exit(0);
}

void Interprete(SymbolList_T **Token, Symbol_T *Symbol)
{
    RecursiveInterprete++;
    int ErrorSign = 0;
    while (*Token)
    {
        if (RecursiveInterprete == 1)
            ErrorSign = setjmp(JumpBuffer);
        if (ErrorSign)
            break;
        GetThing(Token, Symbol);
        if (RecursiveInterprete == 1 || *Token)
            switch (Symbol->Type)
            {
                case TYPE_PROCEDURE:
                case TYPE_NAME:
                case TYPE_FUNCTION:
                    break;
                default:
                    Error(ERROR_WHAT_TO_DO, Symbol->Name + (Symbol->Type == TYPE_NUMBER));
            }
    }
    RecursiveInterprete--;
    return;
}

int main()
{
    CLogoInit();
    SymbolTableInit();

    SymbolList_T *Token;
    SymbolList_T *TokenBackup;
    Symbol_T *Symbol = NewSymbol();

    while (1)
    {
        RecursiveInterprete = 0;
        PrintLN = 1;

        LexerInit(InputStream, &_InputPointer, PrimaryPrompt);
        Token = LexicalAnalyze(&_InputPointer, "\x00");
        TokenBackup = Token;

        Interprete(&Token, Symbol);
        FreeSymbolList(&TokenBackup);
    }

    FreeSymbol(&Symbol);
    return 0;
}
